package com.andromouse;

import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class FileBrowserServer implements Runnable
{
	  private FileServerThread[] clients = new FileServerThread[50];
	  private ServerSocket server = null;
	  private Thread thread = null;
	  private int clientCount = 0;

	  public FileBrowserServer(int port) {
	    try {
	      System.out
	        .println("Binding to port " + port + ", please wait  ...");
	      this.server = new ServerSocket(port);
	      System.out.println("AndroMouse Server started: " + this.server);
	      start();
	    } catch (IOException ioe) {
	      System.out.println("Can not bind to port " + port + ": " + 
	        ioe.getMessage());
	    }
	  }

	  public void run() {
	    while (this.thread != null)
	      try {
	        System.out.println("AndroMouse Waiting for a client ...");
	        addThread(this.server.accept());
	      } catch (IOException ioe) {
	        System.out.println("Server accept error: " + ioe);
	        stop();
	      }
	  }

	  public void start()
	  {
	    if (this.thread == null) {
	      this.thread = new Thread(this);
	      this.thread.start();
	    }
	  }

	  public void stop()
	  {
	    if (this.thread != null) {
	      this.thread.stop();
	      this.thread = null;
	    }
	  }

	  private int findClient(int ID) {
	    for (int i = 0; i < this.clientCount; i++)
	      if (this.clients[i].getID() == ID)
	        return i;
	    return -1;
	  }

	  public synchronized void handle(int ID, String input) throws IOException {
	    System.out.println(input);
	    if (input.equals("CLOSEAMFILE")) {
	      this.clients[findClient(ID)].send(".bye");
	      remove(ID);
	    } else if (input.equals(".DRIVELIST")) {
	      this.clients[0].send(".AM_CLEAR_LIST");

	      if (Utils.isWin) {
	        String[] drives = { "a:\\", "b:\\", "c:\\", "d:\\", "e:\\", "f:\\", 
	          "g:\\", "h:\\", "i:\\", "j:\\", "k:\\", "l:\\", "m:\\", 
	          "n:\\", "o:\\", "p:\\", "q:\\", "r:\\", "s:\\", "t:\\", 
	          "u:\\", "v:\\", "w:\\", "x:\\", "y:\\", "z:\\" };
	        for (int a = 0; a < 26; a++) {
	          File file = new File(drives[a]);
	          if (file.exists())
	            this.clients[0].send(drives[a]);
	        }
	      }
	      else if (!Utils.isWin) {
	        String path = "/";

	        File file = new File(path);
	        if (file.exists()) {
	          File[] list = file.listFiles();
	          for (int j = 0; j < list.length; j++) {
	            String files = list[j].getAbsolutePath();
	            this.clients[0].send(files);
	          }
	        }
	      }
	    } else {
	      sendFiles(input);
	    }
	  }

	  public synchronized void remove(int ID)
	  {
	    int pos = findClient(ID);
	    if (pos >= 0) {
	      FileServerThread toTerminate = this.clients[pos];
	      System.out.println("AndroMouse Removing client thread " + ID + " at " + pos);
	      if (pos < this.clientCount - 1)
	        for (int i = pos + 1; i < this.clientCount; i++)
	          this.clients[(i - 1)] = this.clients[i];
	      this.clientCount -= 1;
	      try {
	        toTerminate.close();
	      } catch (IOException ioe) {
	        System.out.println("AndroMouse Error closing thread: " + ioe);
	      }
	      toTerminate.stop();
	    }
	  }

	  private void addThread(Socket socket) {
	    if (this.clientCount < this.clients.length) {
	      System.out.println("Client accepted: " + socket);
	      this.clients[this.clientCount] = new FileServerThread(this, socket);
	      try {
	        this.clients[this.clientCount].open();
	        this.clients[this.clientCount].start();
	        this.clientCount += 1;
	      } catch (IOException ioe) {
	        System.out.println("Error opening thread: " + ioe);
	      }
	    } else {
	      System.out.println("Client refused: maximum " + this.clients.length + 
	        " reached.");
	    }
	  }

	  public void sendFiles(String input) {
	    String path = input;

	    for (int i = 0; i < this.clientCount; i++) {
	      File folder = new File(path);
	      if (folder.exists())
	        if (folder.isDirectory()) {
	          File[] listOfFiles = folder.listFiles();
	          this.clients[i].send(".AM_CLEAR_LIST");
	          try {
	            int k = listOfFiles.length;

	            if (k > 0)
	            {
	              for (int j = 0; j < k; j++) {
	                String files = listOfFiles[j].getAbsolutePath();
	                File isHiden = new File(files);

	                if (!isHiden.isHidden())
	                  this.clients[i].send(files);
	              }
	              continue;
	            }

	            if (k != 0) continue;
	            this.clients[i].send(".AM_EMPTY_FOLDER");
	            sendFiles(prevPath(input));
	          }
	          catch (NullPointerException e)
	          {
	            this.clients[i].send(".AM_CANNOT_FOLDER");
	            sendFiles(prevPath(input));
	          }
	        } else {
	          if (!folder.isFile()) continue;
	          try {
	            File file = new File(input);
	            Desktop dt = Desktop.getDesktop();
	            if (file.isFile())
	              dt.open(file);
	          } catch (Exception e) {
	            System.out.println("exception");
	          }
	        }
	    }
	  }

	  public String prevPath(String prev)
	  {
	    String upPath = null;
	    if (Utils.isWin) {
	      int a = prev.lastIndexOf("\\");
	      upPath = prev.substring(0, a + 1);
	    } else if (!Utils.isWin) {
	      int a = prev.lastIndexOf("/");
	      upPath = prev.substring(0, a + 1);
	    }
	    return upPath;
	  }
	}
